package com.openlogic.file.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;

import com.openlogic.common.core.exception.ServiceException;
import com.openlogic.file.config.FileConfig;

import org.noear.solon.Solon;
import org.noear.solon.Utils;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import org.noear.solon.cloud.CloudClient;
import org.noear.solon.cloud.model.Media;
import org.noear.solon.core.Props;
import org.noear.solon.core.handle.Result;
import org.noear.solon.core.handle.UploadedFile;

import java.util.ArrayList;
import java.util.List;

/**
 * 文件上传（支持本地、阿里云、七牛云、minio等，想使用哪种，在 pom.xml中解开它的注释并注释掉其它的）
 * @author xm
 */
@Component
public class FileService {

    @Inject
    FileConfig fileConfig;

    /**
     * 单文件上传
     * @param file
     * @return
     */
    public Result<?> uploadFile(UploadedFile file) {
        try {
            if(file == null || file.isEmpty()) {
                throw new ServiceException("文件为空");
            }
            String key = DateUtil.today() + "/" + file.getName();
            // 上传文件
            return upload(key, file);
        } catch (Exception e) {
            return Result.failure(e.getMessage());
        }
    }

    /**
     * 多文件上传
     * @param file
     * @return
     */
    public Result<?> uploadFiles(UploadedFile[] file) {
        try {
            if(file == null || file.length == 0) {
                throw new ServiceException("文件为空");
            }
            for (UploadedFile uploadedFile : file) {
                if(uploadedFile == null || uploadedFile.isEmpty()) {
                    throw new ServiceException("文件为空");
                }
            }
            List<String> list = new ArrayList<>();
            String key = DateUtil.today() + "/";
            for (UploadedFile uploadedFile : file) {
                // 上传文件
                Result<?> result = upload(key + uploadedFile.getName(), uploadedFile);
                if(result.getCode() == Result.SUCCEED_CODE) {
                    list.add(String.valueOf(result.getData()));
                } else {
                    throw new ServiceException("文件上传失败");
                }
            }
            return Result.succeed(list);
        } catch (Exception e) {
            return Result.failure(e.getMessage());
        }
    }

    /**
     * 上传
     * @param key
     * @param file
     */
    private Result<?> upload(String key, UploadedFile file) {
        if(fileConfig.getMaxSize() != -1 && fileConfig.isLimitSize(file.getContentSize())) {
            throw new ServiceException("请上传 " + fileConfig.getMaxSize() + "M 以内的文件");
        }
        if(!fileConfig.getFileType().contains(file.getExtension())) {
            throw new ServiceException("不支持此类文件上传");
        }
        // 上传
        Result<?> result = CloudClient.file().put(key, new Media(file.getContent(), Utils.mime(file.getName())));
        // 处理文件上传结果
        handlerUploadResult(result, key);
        return result;
    }

    /**
     * 处理文件上传结果
     * @param result
     * @param key
     */
    @SuppressWarnings({ "unchecked", "rawtypes"})
    private void handlerUploadResult(Result result, String key) {
        if(result.getCode() != Result.SUCCEED_CODE) {
            return;
        }
        // 阿里云
        if("aliyun".equals(fileConfig.getType())) {
            if(ObjectUtil.isEmpty(result.getData())) {
                Props prop = Solon.cfg().getProp("solon.cloud.aliyun.oss.file");
                // https://world-data-dev.oss-cn-xxx.aliyuncs.com/2023-12-08/123.png
                // https://{bucket}.{endpoint}/{key}
                result.setData("https://" + prop.get("bucket") + "." + prop.get("endpoint") + "/" + key);
            }
        } else if("qiniu".equals(fileConfig.getType())) {
            // 七牛云
            Props prop = Solon.cfg().getProp("solon.cloud.qiniu.kodo.file");
            // https://aaa.bbb.ccc/2023-12-08/123.png
            // {requestPrefix}/{key}
            result.setData(prop.get("requestPrefix") + "/" + key);
        } else if("minio".equals(fileConfig.getType())) {
            // Minio
            Props prop = Solon.cfg().getProp("solon.cloud.minio.file");
            // https://play.min.io/asiatrip/2023-12-08/123.png
            // {endpoint}/{bucket}/{key}
            result.setData(prop.get("endpoint") + "/" + prop.get("bucket") + "/" + key);
        } else {
            // 如果是本地文件上传，需要将返回的文件路径前缀替换，并配合代理服务器（比如 Nginx）实现图片访问
            if(ObjectUtil.isNotEmpty(result.getData())) {
                String defaultBucket = Solon.cfg().getProperty("solon.cloud.file.s3.file.default");
                Props prop = Solon.cfg().getProp("solon.cloud.file.s3.file.buckets." + defaultBucket);
                String newUrl = result.getData().toString().replace(prop.get("endpoint"), prop.get("requestPrefix"));
                result.setData(newUrl);
            }
        }

        /**
         * 本地文件上传说明：
         *   假设此时 Nacos中的配置为：
         *     solon.cloud.file.s3.file:
         *                          default: local_bucket
         *                          buckets:
         *                              local_bucket:
         *                                  endpoint: C:\Users\openlogic\Desktop
         *                                  requestPrefix: http://localhost:90/openlogic-file
         *
         *   则上传后返回的 url为：C:\Users\openlogic\Desktop\local_bucket\2023-12-08\123.png
         *   替换后的 url为：http://localhost:90/openlogic-file\local_bucket\2023-12-08\123.png
         *   此时的 Nginx配置应为：
         *      server {
         *          listen       90;
         *          location /openlogic-file {
         *              alias   C:/Users/openlogic/Desktop/;
         *              autoindex on;
         *          }
         *      }
         *
         *   ！特别注意斜线与反斜线！
         *
         */
    }

}
